gusucode.com > VC下基于winsock2的原始套接子发送程序源码 > VC下基于winsock2的原始套接子发送程序源码/Copy of RawSocket/RawSocket.cpp

    #include <stdio.h> 
#include <winsock2.h> 
#include <ws2tcpip.h> 

// Standard TCP flags
#define URG 0x20 
#define ACK 0x10 
#define PSH 0x08 
#define RST 0x04 
#define SYN 0x02 
#define FIN 0x01

#define SOURCE_PORT 6000 
#define MAX_RECEIVEBYTE 255 

typedef struct ip_hdr //定义IP首部 
{ 
	unsigned char h_verlen; //4位首部长度,4位IP版本号
	unsigned char tos; //8位服务类型TOS
	unsigned short total_len; //16位总长度
	unsigned short ident; //16位标识
	unsigned short frag_and_flags; //3位标识位,13位段偏移
	unsigned char ttl; //8位生存时间TTL
	unsigned char proto; //8位协议(TCP,UDP或其他)
	unsigned short checksum; //16位IP首部校验和
	unsigned int sourceIP; //32位源IP地址
	unsigned int destIP; //32目的IP地址
}IPHEADER; 

typedef struct tsd_hdr //定义TCP伪首部 
{ 
	unsigned long saddr; //源地址
	unsigned long daddr; //目的地址
	char mbz; 
	char ptcl; //协议类型
	unsigned short tcpl; //TCP长度
}PSDHEADER; 

typedef struct tcp_hdr //定义TCP首部
{ 
	USHORT th_sport; //16位源端口
	USHORT th_dport; //16位目的端口
	unsigned int th_seq; //32位序列号
	unsigned int th_ack; //32位确认号
	unsigned char th_lenres; //4位首部长度,6位保留字
	unsigned char th_flag; //6位标识位
	USHORT th_win; //16位窗口大小
	USHORT th_sum; //16位网络校验和
	USHORT th_urp; //16位紧急数据偏移量
}TCPHEADER; 

//CheckSum 计算校验和
USHORT checksum(USHORT *buffer, int size) 
{ 
	//将缓冲区中的数据加起来
	//数据(包括IP头和IP数据)在存储区中实际上是以二进制的形式存放的,
	//所以相当于将这些二进制数据加在一起
	unsigned long cksum=0; 
	while(size >1) 
	{ 
		cksum+=*buffer++; 
		size -=sizeof(USHORT); 
	} 
	if(size ) 
	{ 
		cksum += *(UCHAR*)buffer; 
	} 
	//上面完成了求和运算
	//十六位运算有可能而且很有可能产生超过十六位的结果
	//回卷  取出高十六位 加上 原来的低十六位
	cksum = (cksum >> 16) + (cksum & 0xffff); 
	//再加一次可保证计算值在十六位内
	cksum += (cksum >>16); 
	//取反返回即为校验和
	return (USHORT)(~cksum); 
} 

int main() 
{
	//加载启动winsock.dll
	WSADATA WSAData; 
	if (WSAStartup(MAKEWORD(2,2), &WSAData)!=0) 
	{ 
		printf("WSAStartup Error!\n"); 
		return false; 
	} 
	//创建socket
	SOCKET sock; 
	if ((sock=WSASocket(AF_INET,SOCK_RAW,IPPROTO_RAW,NULL,0,WSA_FLAG_OVERLAPPED))==INVALID_SOCKET) 
	{ 
		printf("Socket Setup Error!\n"); 
		return false; 
	} 
 
	//设置socket选项
	BOOL flag; 
	flag=true; 
	if (setsockopt(sock,IPPROTO_IP, IP_HDRINCL,(char *)&flag,sizeof(flag))==SOCKET_ERROR) 
	{ 
		//IP_HDRINCL IP头包含
		printf("setsockopt IP_HDRINCL error!\n"); 
		return false; 
	} 

	int rect,nTimeOver; 
	nTimeOver=1000; 
	if (setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char*)&nTimeOver, sizeof(nTimeOver))==SOCKET_ERROR) 
	{ 
		printf("setsockopt SO_SNDTIMEO error!\n"); 
		return false; 
	} 

	//地址设置
	SOCKADDR_IN addr_in; 
	addr_in.sin_family=AF_INET; 
	addr_in.sin_port=htons(6000); 
	addr_in.sin_addr.S_un.S_addr=inet_addr("219.242.120.133"); 
	
	IPHEADER ipHeader; 
	TCPHEADER tcpHeader; 
	PSDHEADER psdHeader; 

	//填充IP首部
	//version and length
	//here,sizeof( ipHeader ) is 20
	ipHeader.h_verlen=(4<<4 | sizeof(ipHeader)/sizeof(unsigned long)); 
	ipHeader.tos=0; 
	ipHeader.total_len=htons(sizeof(ipHeader)+sizeof(tcpHeader)); 
	ipHeader.ident=1; 
	ipHeader.frag_and_flags=0; 
	ipHeader.ttl=128; 
	//ipHeader.proto=IPPROTO_TCP; 
	ipHeader.proto=IPPROTO_UDP; 
	ipHeader.checksum=0; 
	ipHeader.sourceIP=inet_addr("219.242.120.133"); 
	ipHeader.destIP=inet_addr("219.242.120.134"); 
	
	//填充TCP首部
	tcpHeader.th_dport=htons(6000); 
	tcpHeader.th_sport=htons(SOURCE_PORT); //源端口号
	tcpHeader.th_seq=htonl(0x12345678); 
	tcpHeader.th_ack=0; 
	tcpHeader.th_lenres=(sizeof(tcpHeader)/4<<4|0); 
	tcpHeader.th_flag=2; //修改这里来实现不同的标志位探测。2是SYN,1是FIN,16是ACK探测等等
	tcpHeader.th_win=htons(512); 
	tcpHeader.th_urp=0; 
	tcpHeader.th_sum=0; 
	
	psdHeader.saddr=ipHeader.sourceIP; 
	psdHeader.daddr=ipHeader.destIP; 
	psdHeader.mbz=0; 
	psdHeader.ptcl=IPPROTO_TCP; 
	psdHeader.tcpl=htons(sizeof(tcpHeader)); 
	
	//计算校验和
	char szSendBuf[60]={0};
	memcpy(szSendBuf, &psdHeader, sizeof(psdHeader)); 
	memcpy(szSendBuf+sizeof(psdHeader), &tcpHeader, sizeof(tcpHeader)); 
	tcpHeader.th_sum=checksum((USHORT *)szSendBuf,sizeof(psdHeader)+sizeof(tcpHeader)); 
	
	memcpy(szSendBuf, &ipHeader, sizeof(ipHeader)); 
	memcpy(szSendBuf+sizeof(ipHeader), &tcpHeader, sizeof(tcpHeader)); 
	memset(szSendBuf+sizeof(ipHeader)+sizeof(tcpHeader), 0, 4); 
	ipHeader.checksum=checksum((USHORT *)szSendBuf, sizeof(ipHeader)+sizeof(tcpHeader)); 
	
	memcpy(szSendBuf, &ipHeader, sizeof(ipHeader)); 
	
	//发送数据通过原始套接字
	//此时,我们发送的数据为IP包
	//其中的数据就是我们之前填充的TCP头
	int i=100;
	while(i)
	{
		//rect = send(sock,szSendBuf,sizeof(ipHeader)+sizeof(tcpHeader),0);
		rect=sendto(sock, szSendBuf, sizeof(ipHeader)+sizeof(tcpHeader), 
			0, (SOCKADDR *)&addr_in, sizeof(addr_in)); 
		if (rect==SOCKET_ERROR) 
		{ 
			printf("send error!:%d\n",WSAGetLastError()); 
			return false; 
		} 
		else 
			printf("send ok!\n"); 
		i--;
	}
	closesocket(sock); 
	WSACleanup(); 
	
	return 0; 
}